﻿//
// SampleSerialLEDShield
// Kentaro Sekimoto
// 2014/07/08
// Product
// http://www.switch-science.com/catalog/1740/
// Based on
// https://github.com/carcon999/SerialLedController
//
//#define NETDUINO
//#define CQFM3DUINO
#define GR_SAKURA
//#define KS_MB9BF568
//#define SK_FM4

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.IO.Ports;

namespace SampleSerialLEDShield
{
    public class Program
    {
        private const int TIMEOUT = 10000;

        public static byte[] cmdPlay = new byte[] { 0x94, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        public static byte[] cmdStop = new byte[] { 0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        public static byte[][] cmdPlayList_RainbowI5ms = new byte[][] {
        new byte[]{ 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec Start. */
        new byte[]{ 0x90, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, /* system */
        new byte[]{ 0x95, 0x36, 0x01, 0x05, 0xF4, 0x01, 0x00, 0x00 }, /* Rainbow mode:Individual 5ms */
        new byte[]{ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec End. */
        };

        public static byte[][] cmdPlayList_RainbowA5ms = new byte[][] {
        new byte[]{ 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec Start. */
        new byte[]{ 0x90, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, /* system */
        new byte[]{ 0x95, 0x36, 0x00, 0x05, 0xF4, 0x01, 0x00, 0x00 }, /* Rainbow mode:all 5ms*/
        new byte[]{ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec End. */
        };

        public static byte[][] cmdPlayList_RainbowI50ms = new byte[][] {
        new byte[]{ 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec Start. */
        new byte[]{ 0x90, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, /* system */
        new byte[]{ 0x95, 0x36, 0x01, 0x32, 0xF4, 0x01, 0x00, 0x00 }, /* Rainbow mode:Individual 50ms */
        new byte[]{ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec End. */
        };

        public static byte[][] cmdPlayList_RainbowA50ms = new byte[][] {
        new byte[]{ 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec Start. */
        new byte[]{ 0x90, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, /* system */
        new byte[]{ 0x95, 0x36, 0x00, 0x32, 0xF4, 0x01, 0x00, 0x00 }, /* Rainbow mode:all 50ms*/
        new byte[]{ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec End. */
        };

        public static byte[][] cmdPlayList0 = new byte[][]{
        new byte[]{ 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Rec Start. */
        new byte[]{ 0x90, 0x01, 0x00, 0x00, 0x20, 0x00, 0x0A, 0x00 }, /* System */
        new byte[]{ 0x8C, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01 }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01 }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x2A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x2A, 0x00, 0x83, 0xC1, 0x83, 0xC1 }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x2A, 0x00, 0x83, 0xC1, 0x83, 0xC1 }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x2A, 0x00, 0x03, 0xC0, 0x03, 0xC0 }, /* Color */
        new byte[]{ 0x8C, 0x3F, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x1A, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }, /* Color */
        new byte[]{ 0x8C, 0x1A, 0x3F, 0x00, 0x00, 0xC0, 0x03, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x1A, 0x3F, 0x00, 0x00, 0xC0, 0x03, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x1A, 0x3F, 0x00, 0x00, 0xC0, 0x03, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x1A, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x00, 0x16, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF }, /* Color */
        new byte[]{ 0x8C, 0x00, 0x16, 0x3F, 0x00, 0xC0, 0x03, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x00, 0x16, 0x3F, 0x00, 0xC0, 0x03, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x00, 0x16, 0x3F, 0x00, 0xC0, 0x03, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x00, 0x16, 0x3F, 0x00, 0x00, 0x00, 0x00 }, /* Color */
        new byte[]{ 0x8C, 0x26, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF }, /* Color */
        new byte[]{ 0x8C, 0x26, 0x00, 0x3F, 0x03, 0xC0, 0x03, 0xC0 }, /* Color */
        new byte[]{ 0x8C, 0x26, 0x00, 0x3F, 0x03, 0xC0, 0x03, 0xC0 }, /* Color */
        new byte[]{ 0x8C, 0x26, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF }, /* Color */
        new byte[]{ 0x8C, 0x26, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00 }, /* Color */
        new byte[]{ 0x93, 0x00, 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00 }, /* Loop */
        new byte[]{ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }  /* Rec End. */
        };
        static bool readDone = false;

#if GR_SAKURA
        public static Cpu.Pin PinReset = (Cpu.Pin)20;     // D4
        public static Cpu.Pin PinTrigger = (Cpu.Pin)21;   // D5
#endif
        public static SerialPort serial = new SerialPort(Serial.COM1, 19200, Parity.None, 8, StopBits.One);


        public static bool WriteResponse(SerialPort sp, byte[] cmd)
        {
            int timeout = TIMEOUT;
            sp.DiscardInBuffer();
            readDone = false;
            sp.Write(cmd, 0, cmd.Length);
            while (timeout-- > 0)
            {
                Thread.Sleep(10);
                if (readDone == true)
                {
                    return true;
                }
            }
            Debug.Print("Err: CmdSend");
            return false;
        }

        public static void Reset()
        {
            OutputPort PortReset = new OutputPort(PinReset, true);
            PortReset.Write(false);
            Thread.Sleep(200);
            PortReset.Write(true);
            Thread.Sleep(200);
        }

        public static void Demo()
        {
            OutputPort PortReset = new OutputPort(PinTrigger, true);
            PortReset.Write(false);
            Thread.Sleep(500);
            PortReset.Write(true);
        }

        public static bool CmdSend(SerialPort sp, byte[] cmd)
        {
            WriteResponse(sp, cmdStop);
            bool flag = WriteResponse(sp, cmd);
            return flag;
        }

        public static bool CmdListSend(SerialPort sp, byte[][] cmdList)
        {
            bool flag;
            for (int i = 0; i < cmdList.Length; i++)
            {
                flag = CmdSend(sp, cmdList[i]);
                if (flag == false)
                {
                    Debug.Print("Err: CmdListSend no=" + i.ToString());
                    return false;
                }
            }
            Thread.Sleep(10);
            return true;
        }

        static void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort serial = (SerialPort)sender;
            byte[] rs = new byte[1];
            int len = serial.Read(rs, 0, rs.Length);
            //Debug.Print(rs[0].ToString("X2"));
            readDone = true;
        }

        public static void Main()
        {
            int i = 0;
            serial.DataReceived += new SerialDataReceivedEventHandler(Serial_DataReceived);
            serial.Open();
            Reset();
            CmdSend(serial, cmdStop);
            while (true)
            {
                Debug.Print("Demo " + i.ToString());
                switch (i % 2)
                {
                    case 0:
                        CmdListSend(serial, cmdPlayList_RainbowI5ms);
                        break;
                    case 1:
                        CmdListSend(serial, cmdPlayList_RainbowA5ms);
                        break;
                    //case 2:
                    //    CmdListSend(serial, cmdPlayList_RainbowI50ms);
                    //    break;
                    //case 3:
                    //    CmdListSend(serial, cmdPlayList_RainbowA50ms);
                    //    break;
                    //case 4:
                    //    CmdListSend(serial, cmdPlayList0);
                    //    break;
                    default:
                        break;

                }
                CmdSend(serial, cmdPlay);
                Thread.Sleep(1000);
                CmdSend(serial, cmdStop);
                i++;
            }
        }

    }
}
